package com.bb.flow.parser.impl.parsejson.parsenode;

import com.alibaba.fastjson2.JSONObject;
import com.bb.flow.api.exception.ParseException;
import com.bb.flow.config.AbstractConfigNode;
import com.bb.flow.config.enumtype.NodeType;
import com.bb.flow.config.enumtype.WaitType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;

import static com.bb.flow.util.Tools.isEmptyOrNull;

/**
 * @author bigbeard
 * 解析流程中的流程节点的基本信息
 */
public class ParseNodeBaseInfo {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 解析节点基本信息
     *
     * @param configNode       节点
     * @param jsonObject       待解析JSON对象
     * @param flowTemplateName 流程模版名称
     * @return true:解析成功,否则失败
     */
    public boolean parseNodeBaseInfo(
            AbstractConfigNode configNode,
            JSONObject jsonObject, String flowTemplateName) throws ParseException {
        String nodeKey = jsonObject.getString("NodeKey");
        if (isEmptyOrNull(nodeKey)) {
            String s = String.format("流程模版[%s]中节点名称[NodeKey]不能为空", flowTemplateName);
            throw new ParseException(s);
        }

        configNode.setNodeKey(nodeKey);
        Boolean startNode = jsonObject.getBoolean("StartNode");
        configNode.setStartNode(Objects.requireNonNullElse(startNode, false));

        String nextNodeKey = jsonObject.getString("NextNodeKey");
        configNode.setNextNodeKey(nextNodeKey);
        String waitType2 = jsonObject.getString("WaitType");
        if (null != waitType2) {
            waitType2 = waitType2.toUpperCase();
        } else {
            logger.warn("流程模版[{}]中的节点[{}]未配置等待方式[WaitType]", flowTemplateName, nodeKey);
        }
        WaitType waitType1 = getWaitType(waitType2, flowTemplateName, nodeKey);
        configNode.setWaitType(waitType1);
        Integer waitTime = jsonObject.getInteger("WaitTime");
        if (null != waitTime) {
            configNode.setWaitTime(waitTime);
        }

        String otherInfo = jsonObject.getString("OtherInfo");
        configNode.setOtherInfo(otherInfo);
        return true;
    }


    /**
     * 等待类型转换
     *
     * @param type             等待类型
     * @param flowTemplateName 流程模版名称
     * @return 数据类型（枚举）
     */
    private WaitType getWaitType(String type, String flowTemplateName, String nodeKey) {
        if (isEmptyOrNull(type)) {
            logger.warn("流程模版[{}]中的节点[{}]等待类型转换失败！待转换的等待类型值未配置或者为空,系统按照不等待进行处理",
                    flowTemplateName, nodeKey);
            return WaitType.NOT_WAIT;
        }
        if (type.equals(WaitType.NOT_WAIT.toString())) {
            return WaitType.NOT_WAIT;
        } else if (type.equals(WaitType.WAIT_ALL.toString())) {
            return WaitType.WAIT_ALL;
//        } else if (type.equals(WaitType.WAIT_ONE.toString())) {
//            return WaitType.WAIT_ONE;
        } else if (type.equals(WaitType.WAIT_TIME.toString())) {
            return WaitType.WAIT_TIME;
        } else {
            logger.warn("流程模版[{}]中的节点[{}]配置的待类型系统不可识别,不识别的值为:{},系统按照不等待进行处理",
                    flowTemplateName, nodeKey, type);
            return WaitType.NOT_WAIT;
        }
    }

    /**
     * 转换节点类型
     *
     * @param type             节点类型字符串
     * @param flowTemplateName 流程模版名称
     * @return 节点类型枚举
     */
    protected NodeType getNodeType(String type, String flowTemplateName) {

        if (null == type || type.isEmpty()) {
            logger.error("流程模版[{}]中节点未配置[NodeType]节点类型属性", flowTemplateName);
            return null;
        }
        if (type.toUpperCase().equals(NodeType.FUNCTION_NODE.toString())) {
            return NodeType.FUNCTION_NODE;
        } else if (type.toUpperCase().equals(NodeType.CONTAINER_NODE.toString())) {
            return NodeType.CONTAINER_NODE;
        } else if (type.toUpperCase().equals(NodeType.SUBFLOW_NODE.toString())) {
            return NodeType.SUBFLOW_NODE;
        } else if (type.toUpperCase().equals(NodeType.JUDGE_NODE.toString())) {
            return NodeType.JUDGE_NODE;
        } else {
            logger.error("流程节点类型解析错误！流程模版[{}]中,未知流程节点[{}]", flowTemplateName, type);
            return null;
        }
    }
}
